#include <iostream>
#include "../inc/HoughSpace4D.h"
#include "../inc/tools.h"

using namespace std;

HoughSpace4D::HoughSpace4D()
{
        bot = vcg::Point4f(0,0,0,0);
        top = vcg::Point4f(0,0,0,0);
        
        nbFrameA = 0;
        nbFrameB = 0;
	nbFrameC = 0;
        nbFrameR = 0;
        
        aFrameMax = 0;
        bFrameMax = 0;
	cFrameMax = 0;
        rFrameMax = 0;

        frameSizeA = 0;
        frameSizeB = 0;
	frameSizeC = 0;
        frameSizeR = 0;
        
        scoreMax = 0;
        scoreTotal = 0;
        
        frames = NULL;
}

HoughSpace4D::HoughSpace4D(int _mode, vcg::Point4f _bot, vcg::Point4f _top, float _a, float _b, float _c, float _r)
{
        bot = _bot;
        top = _top;
        
        aFrameMax = 0;
        bFrameMax = 0;
		cFrameMax = 0;
        rFrameMax = 0;
        
        scoreMax = 0;
        scoreTotal = 0;
        
        if ( _mode == RESOLUTION )
        {
                nbFrameA = (int)_a;
                nbFrameB = (int)_b;
				nbFrameC = (int)_c;
                nbFrameR = (int)_r;
                
                frameSizeA = ( _top[0] - _bot[0] ) / nbFrameA;
                frameSizeB = ( _top[1] - _bot[1] ) / nbFrameB;
				frameSizeC = ( _top[2] - _bot[2] ) / nbFrameC;
                frameSizeR = ( _top[3] - _bot[3] ) / nbFrameR;
        }
        
        if ( _mode == SIZE )
        {
                frameSizeA = _a;
                frameSizeB = _b;
				frameSizeC = _c;
                frameSizeR = _r;
                
                nbFrameA = (int) (( _top[0] - _bot[0] ) / frameSizeA) + 1;
                nbFrameB = (int) (( _top[1] - _bot[1] ) / frameSizeB) + 1;
				nbFrameC = (int) (( _top[2] - _bot[2] ) / frameSizeC) + 1;
                nbFrameR = (int) (( _top[3] - _bot[3] ) / frameSizeR) + 1;
        }
        
        if ( _mode != SIZE && _mode != RESOLUTION )
        {
                cout<<"Mauvais parametre pour la création de HoughSpace : seuls RESOLUTION et SIZE sont acceptés comme mode"<<endl;
        }
        
        frames = (HoughFrame4D****) malloc ( nbFrameA * sizeof ( HoughFrame4D*** ) );
        for ( int i = 0 ; i < nbFrameA ; i++ )
        {
                frames[i] = (HoughFrame4D***) malloc ( nbFrameB * sizeof ( HoughFrame4D** ) );
                
                for ( int j = 0 ; j < nbFrameB ; j++ )
                {
					frames[i][j] = (HoughFrame4D**) malloc ( nbFrameC * sizeof (HoughFrame4D* ) );
					for ( int k = 0 ; k < nbFrameC ; k++ )
					{
						frames[i][j][k] = (HoughFrame4D*) malloc ( nbFrameR * sizeof (HoughFrame4D) );
								
						for ( int l = 0 ; l < nbFrameR ; l++ )
						{
							vcg::Point4f pBot, pTop;
		
							pBot = vcg::Point4f( bot[0] + ( i * frameSizeA), bot[1] + ( j * frameSizeB ), bot[2] + ( k * frameSizeC ), bot[3] + ( l * frameSizeR ));
							pTop = vcg::Point4f( pBot[0] + frameSizeA, pBot[1] + frameSizeB, pBot[2] + frameSizeC , pBot[3] + frameSizeR );
							
							frames[i][j][k][l].setPointBot( pBot );
							frames[i][j][k][l].setPointTop( pTop );
							frames[i][j][k][l].updateMiddlePoint();
							frames[i][j][k][l].setScore( 0 );
						}
					}
                }
        }
}


HoughSpace4D::~HoughSpace4D()
{
        for ( int i = 0 ; i < nbFrameA ; i++ )
        {
                for ( int j = 0 ; j < nbFrameB ; j++ )
                {
		    for ( int k = 0 ; k < nbFrameC ; k++ )
		    {
			free(frames[i][j][k]);
		    }

		    free(frames[i][j]);
                }
                
                free (frames[i]);
        }
        
        free(frames);
}

void HoughSpace4D::init(int _mode, vcg::Point4f _bot, vcg::Point4f _top, float _a, float _b, float _c, float _r)
{
        if ( frames != NULL )
        {
                cout<<"Erreur, l'espace de Hough a déjà été initialisé"<<endl;
                return;
        }

        bot = _bot;
        top = _top;
        
        aFrameMax = 0;
        bFrameMax = 0;
	cFrameMax = 0;
        rFrameMax = 0;
        
        scoreMax = 0;
        scoreTotal = 0;
        
        if ( _mode == RESOLUTION )
        {
                nbFrameA = (int)_a;
                nbFrameB = (int)_b;
		nbFrameC = (int)_c;
                nbFrameR = (int)_r;
                
                frameSizeA = ( _top[0] - _bot[0] ) / nbFrameA;
                frameSizeB = ( _top[1] - _bot[1] ) / nbFrameB;
		frameSizeC = ( _top[2] - _bot[2] ) / nbFrameC;
                frameSizeR = ( _top[3] - _bot[3] ) / nbFrameR;
        }
        
        if ( _mode == SIZE )
        {
                frameSizeA = _a;
                frameSizeB = _b;
		frameSizeC = _c;
                frameSizeR = _r;
                
                nbFrameA = (int) (( _top[0] - _bot[0] ) / frameSizeA) + 1;
                nbFrameB = (int) (( _top[1] - _bot[1] ) / frameSizeB) + 1;
		nbFrameC = (int) (( _top[2] - _bot[2] ) / frameSizeC) + 1;
                nbFrameR = (int) (( _top[3] - _bot[3] ) / frameSizeR) + 1;
        }
        
        if ( _mode != SIZE && _mode != RESOLUTION )
        {
                cout<<"Mauvais parametre pour la création de HoughSpace : seuls RESOLUTION et SIZE sont acceptés comme mode"<<endl;
        }
        
        frames = (HoughFrame4D****) malloc ( nbFrameA * sizeof ( HoughFrame4D*** ) );
        for ( int i = 0 ; i < nbFrameA ; i++ )
        {
                frames[i] = (HoughFrame4D***) malloc ( nbFrameB * sizeof ( HoughFrame4D** ) );
                
                for ( int j = 0 ; j < nbFrameB ; j++ )
                {
                        frames[i][j] = (HoughFrame4D**) malloc ( nbFrameC * sizeof (HoughFrame4D*) );
                        
                        for ( int k = 0 ; k < nbFrameC ; k++ )
                        {
				frames[i][j][k] = (HoughFrame4D*) malloc ( nbFrameR * sizeof (HoughFrame4D) );

				for ( int l = 0 ; l < nbFrameR ; l++ )
				{
					vcg::Point4f pBot, pTop;

					pBot = vcg::Point4f( bot[0] + ( i * frameSizeA), bot[1] + ( j * frameSizeB ), bot[2] + ( k * frameSizeC ), bot[3] + ( l * frameSizeR ));
					pTop = vcg::Point4f( pBot[0] + frameSizeA, pBot[1] + frameSizeB, pBot[2] + frameSizeC , pBot[3] + frameSizeR );

					frames[i][j][k][l].setPointBot( pBot );
					frames[i][j][k][l].setPointTop( pTop );
					frames[i][j][k][l].updateMiddlePoint();
					frames[i][j][k][l].setScore( 0 );
				}
                        }
                }
        }
}

/*void HoughSpace4D::fill(vector <Circle> _tabCircles)
{
        int a, b, r;
        scoreMax = 0;

        if(_tabCircles.size() > 0)
        {
                for(int i=0; i < (int)_tabCircles.size(); i++)
                {
                        _tabCircles[i].setABR(_tabCircles[i].getA() - bot.getX(), _tabCircles[i].getB() - bot.getY(), _tabCircles[i].getR() - bot.getZ());

                        a = (int)((_tabCircles[i].getA())/frameSizeA);
                        b = (int)((_tabCircles[i].getB())/frameSizeB);
                        r = (int)((_tabCircles[i].getR())/frameSizeR);

                        if ( a >= nbFrameA )
                                a = nbFrameA-1;
                        
                        if ( b >= nbFrameB )
                                b = nbFrameB-1;
                        
                        if ( r >= nbFrameR )
                                r = nbFrameR-1;
                        
                        _tabCircles[i].setABR(_tabCircles[i].getA() + bot.getX(), _tabCircles[i].getB() + bot.getY(), _tabCircles[i].getR() + bot.getZ());

                        frames[a][b][r].incrementScore();

                        if(frames[a][b][r].getScore() > scoreMax)
                        {
                                scoreMax = frames[a][b][r].getScore();
                                aFrameMax = frames[a][b][r].getBotPoint().getX() + frameSizeA/2;
                                bFrameMax = frames[a][b][r].getBotPoint().getY() + frameSizeB/2;
                                rFrameMax = frames[a][b][r].getBotPoint().getZ() + frameSizeR/2;
                        }
                        
                }
        }
}*/

void HoughSpace4D::threshold(vector <Circle> &_rslt, int _thresh)
{       
        for ( int i = 0 ; i < nbFrameA ; i++ )
                for ( int j = 0 ; j < nbFrameB ; j++ )
                        for ( int k = 0 ; k < nbFrameC ; k++ )
				for ( int l = 0 ; l < nbFrameR ; l++ )
					if ( this->getScore(i,j,k,l) > _thresh )
					{
						_rslt.push_back ( Circle (  ((float)i * frameSizeA) + this->bot[0] + (frameSizeA/(float)2),
									   ((float)j * frameSizeB) + this->bot[1] + (frameSizeB/(float)2),
									   ((float)k * frameSizeC) + this->bot[2] + (frameSizeC/(float)2),
									   ((float)l * frameSizeR) + this->bot[3] + (frameSizeR/(float)2)
									   ));
					}
}

vector<Circle> HoughSpace4D::threshold(int _thresh)
{
        vector<Circle> rslt;
        
        rslt.clear();
        
        for ( int i = 0 ; i < nbFrameA ; i++ )
			for ( int j = 0 ; j < nbFrameB ; j++ )
				for ( int k = 0 ; k < nbFrameC ; k++ )
					for ( int l = 0 ; l < nbFrameR ; l++ )
						if ( this->getScore(i,j,k,l) > _thresh )
						{
							rslt.push_back ( Circle (  ((float)i * frameSizeA) + this->bot[0] + (frameSizeA/(float)2),
										   ((float)j * frameSizeB) + this->bot[1] + (frameSizeB/(float)2),
										   ((float)k * frameSizeC) + this->bot[2] + (frameSizeC/(float)2),
										   ((float)l * frameSizeR) + this->bot[3] + (frameSizeR/(float)2)
										   ));
						}

        return rslt;
}

vector<Circle> HoughSpace4D::threshold(float _thresh1, float _thresh2)
{
        vector<Circle> rslt;
        int thresh;
        
        rslt.clear();
        
        for ( int i = 0 ; i < nbFrameA ; i++ )
			for ( int j = 0 ; j < nbFrameB ; j++ )
				for ( int k = 0 ; k < nbFrameC ; k++ )
					for ( int l = 0 ; l < nbFrameR ; l++ )
					{
						thresh = (int)((((1.0/(float)scoreTotal)* (_thresh2 - _thresh1)) + _thresh1) / 100.0) * scoreTotal;
	
						if ( this->getScore(i,j,k,l) > thresh )
						{
							rslt.push_back ( Circle (  ((float)i * frameSizeA) + this->bot[0] + (frameSizeA/(float)2),
										   ((float)j * frameSizeB) + this->bot[1] + (frameSizeB/(float)2),
										   ((float)k * frameSizeC) + this->bot[2] + (frameSizeC/(float)2),
										   ((float)l * frameSizeR) + this->bot[3] + (frameSizeR/(float)2)
										   ));
						}
					}

        return rslt;
}

void HoughSpace4D::increment(int _a, int _b, int _c, int _r)
{
        this->frames[_a][_b][_c][_r].incrementScore();
        this->scoreTotal ++;
}

void HoughSpace4D::increment ( int _a, int _b, int _c, int _r , int _val)
{
        this->frames[_a][_b][_c][_r].incrementScore(_val);
        this->scoreTotal += _val;
}

void HoughSpace4D::addCircle(Circle _c)
{
    // tests dans grille
    _c.setABCR(_c.getA() - getBot()[0], _c.getB() - getBot()[1],
               _c.getC() - getBot()[2], _c.getR() - getBot()[3]);

    float indexAf = ((_c.getA())/getFrameSizeA());
    float indexBf = ((_c.getB())/getFrameSizeB());
    float indexCf = ((_c.getC())/getFrameSizeC());
    float indexRf = ((_c.getR())/getFrameSizeR());

    // Si le cercle est hors de l'espace de Hough -> suppression par une score nul
    if (( indexAf >= getNbFrameA() ) || ( indexBf >= getNbFrameB() ) || ( indexCf >= getNbFrameC() ) || ( indexRf >= getNbFrameR() ) ||
        ( indexAf < 0 ) || ( indexBf < 0 ) || ( indexCf < 0 ) || ( indexRf < 0 ))
    {
        _c.setScore(0);
    }
    else
    {
        // On est dans l'espace de Hough, on peut tronquer pour calculer l'indice de la cellule
        int indexA = (int) indexAf ;
        int indexB = (int) indexBf ;
        int indexC = (int) indexCf ;
        int indexR = (int) indexRf ;

        increment( indexA, indexB, indexC, indexR );

        if( getScore( indexA, indexB, indexC, indexR ) > getScoreMax())
        {
            setScoreMax( getScore( indexA, indexB, indexC, indexR ));
            setAFrameMax( getHoughFrame( indexA, indexB, indexC, indexR ).getBotPoint()[0] + getFrameSizeA()/2);
            setBFrameMax( getHoughFrame( indexA, indexB, indexC, indexR ).getBotPoint()[1] + getFrameSizeB()/2);
            setCFrameMax( getHoughFrame( indexA, indexB, indexC, indexR ).getBotPoint()[2] + getFrameSizeC()/2);
            setRFrameMax( getHoughFrame( indexA, indexB, indexC, indexR ).getBotPoint()[3] + getFrameSizeR()/2);
        }
    }
}

//void HoughSpace4D::addCircle(Circle _c)
//{
//    // tests dans grille
//        _c.setABCR(_c.getA() - getBot()[0], _c.getB() - getBot()[1],
//                   _c.getC() - getBot()[2], _c.getR() - getBot()[3]);

//	int indexA = abs((int)((_c.getA())/getFrameSizeA()));
//	int indexB = abs((int)((_c.getB())/getFrameSizeB()));
//	int indexC = abs((int)((_c.getC())/getFrameSizeC()));
//	int indexR = abs((int)((_c.getR())/getFrameSizeR()));

//	if ( indexA >= getNbFrameA() )
//			indexA= getNbFrameA()-1;

//	if ( indexB >= getNbFrameB() )
//			indexB = getNbFrameB()-1;

//	if ( indexC >= getNbFrameC() )
//			indexC = getNbFrameC()-1;

//	if ( indexR >= getNbFrameR() )
//			indexR = getNbFrameR()-1;

//	increment( indexA, indexB, indexC, indexR );

//	if( getScore( indexA, indexB, indexC, indexR ) > getScoreMax())
//	{
//			setScoreMax( getScore( indexA, indexB, indexC, indexR ));
//			setAFrameMax( getHoughFrame( indexA, indexB, indexC, indexR ).getBotPoint()[0] + getFrameSizeA()/2);
//			setBFrameMax( getHoughFrame( indexA, indexB, indexC, indexR ).getBotPoint()[1] + getFrameSizeB()/2);
//			setCFrameMax( getHoughFrame( indexA, indexB, indexC, indexR ).getBotPoint()[2] + getFrameSizeC()/2);
//			setRFrameMax( getHoughFrame( indexA, indexB, indexC, indexR ).getBotPoint()[3] + getFrameSizeR()/2);
//	}

//}

void HoughSpace4D::saveCircles( vector<Circle> _circles, const QString& _fileName )
{
	ofstream file ( _fileName.toStdString().c_str(), ios::out | ios::trunc);
	
	if( !file )
	{
		cout<<"Erreur lors de l'enregistrement dans \""<<_fileName.toStdString()<<"\""<<endl;
		return;
	}
	
	file<<_circles.size()<<std::endl;
	
	for ( unsigned int i = 0 ; i < _circles.size() ; i++ )
	{
		file<<_circles[i].getA()<<" "<<_circles[i].getB()<<" "<<_circles[i].getC()<<" "<<_circles[i].getR()<<std::endl;
	}
	
	file.close();
}

void HoughSpace4D::addPointVector_old ( vcg::Point3f _vertex, vcg::Point3f _vector )
{


	// On ramene les coordonnées du point au repère local
	_vertex[0] -= getBot()[0];
	_vertex[1] -= getBot()[1];
	_vertex[1] -= getBot()[2];

	// On trouve toutes les cases alignées à _vertex selon le vecteur _vector
        for ( int i = 0 ; i < nbFrameA ; i++ )
                for ( int j = 0 ; j < nbFrameB ; j++ )
                        for ( int k = 0 ; k < nbFrameC ; k++ )
			{
				// On calcule le vecteur reliant_vertex au point défini par la case actuelle
				vcg::Point3f centreCurrentFrame(i*frameSizeA + frameSizeA/2, j*frameSizeB + frameSizeB/2, k*frameSizeC + frameSizeC/2);
				vcg::Point3f vectTemp = _vertex - centreCurrentFrame;
				// Si ce vecteur est parallèle au _vector passé en paramètre
				if((vectTemp[0] / _vector[0] == vectTemp[1] / _vector[1]) && (vectTemp[0] / _vector[0] == vectTemp[2] / _vector[2]))
				{
					// on calcule le rayon du cercle
					float rayon = sqrt(pow(_vertex[0] - centreCurrentFrame[0], 2) + pow(_vertex[1] - centreCurrentFrame[1], 2) + pow(_vertex[2] - centreCurrentFrame[2], 2));
					// on trouve la case correspondant à ce rayon
					int indexR = abs((int)(rayon/getFrameSizeR()));
					if ( indexR >= getNbFrameR() )
							indexR = getNbFrameR()-1;

					// On incrémente enfin la case de coordonnées correspondante
					increment( i, j, k, indexR );

					if( getScore( i, j, k, indexR ) > getScoreMax())
					{
							setScoreMax( getScore( i, j, k, indexR ));
							setAFrameMax( getHoughFrame( i, j, k, indexR ).getBotPoint()[0] + getFrameSizeA()/2);
							setBFrameMax( getHoughFrame( i, j, k, indexR ).getBotPoint()[1] + getFrameSizeB()/2);
							setCFrameMax( getHoughFrame( i, j, k, indexR ).getBotPoint()[2] + getFrameSizeC()/2);
							setRFrameMax( getHoughFrame( i, j, k, indexR ).getBotPoint()[3] + getFrameSizeR()/2);
					}
				}
			}
}

void HoughSpace4D::addPointVector ( vcg::Point3f _vertex, vcg::Point3f _vector, float _rMax )
{
	if ( _vector[0] > _vector[1] )
	{
		if ( _vector[0] > _vector[2] )
		{
			/* Si la composante en x de la normale est la plus importante */
			addPointVectorX( _vertex, _vector, _rMax );
		}
		
		else
		{
			/* C'est la composante en Z la plus importante */
			addPointVectorZ( _vertex, _vector, _rMax );
		}
	}
	
	else
	{
		if ( _vector[1] > _vector[2] )
		{
			/* Composante Y la plus importante */
			addPointVectorY( _vertex, _vector, _rMax );
		}
		
		else
		{
			/* Composante Z la plus importante */
			addPointVectorZ( _vertex, _vector, _rMax );
		}
	}
}

void HoughSpace4D::addPointVectorX (vcg::Point3f _vertex, vcg::Point3f _vector, float _rMax)
{
        float k = 0;
	float x = 0;
	float y = 0;
	float z = 0;
	float r = 0;
	
	for ( int i = 0 ; i < this->getNbFrameA() ; i++ )
	{
		/* On trouve le k de l'équation paramétrée de la droite portée par le vecteur _vector qui correspond au point sur la droite 
		   et d'abscisse l'abcsisse du centre de la ieme case de l'espace de Hough selon l'axe x */
		x = this->getFrame(i,0,0,0)->getMiddlePoint()[0];
		k = ( x - _vertex[0] ) / _vector[0];
		
		/* On en déduit donc le y et le z */
		y = _vertex[1] + ( k * _vector[1] );
		z = _vertex[2] + ( k * _vector[2] );
		
		/* on calcule le rayon entre le point trouvé et le point d'entrée (_vertex) */
		r = distPoint( _vertex, x, y, z );
		
		if ( r < _rMax )
		{		
			/* Et on incrémente cette case dans l'espace de Hough */
			this->addCircle( Circle(x,y,z,r) );
		}
	}
}

void HoughSpace4D::addPointVectorY ( vcg::Point3f _vertex, vcg::Point3f _vector, float _rMax )
{
        float k = 0;
	float x = 0;
	float y = 0;
	float z = 0;
	float r = 0;
	
	for ( int i = 0 ; i < this->getNbFrameB() ; i++ )
	{
		y = this->getFrame(0,i,0,0)->getMiddlePoint()[1];
		k = ( y - _vertex[1] ) / _vector[1];
		
		x = _vertex[0] + ( k * _vector[0] );
		z = _vertex[2] + ( k * _vector[2] );
		
		r = distPoint( _vertex, x, y, z );
		
		if ( r < _rMax )
		{
			/* Et on incrémente cette case dans l'espace de Hough */
			this->addCircle( Circle(x,y,z,r) );
		}
	}
}

void HoughSpace4D::addPointVectorZ ( vcg::Point3f _vertex, vcg::Point3f _vector, float _rMax )
{	
        float k = 0;
	float x = 0;
	float y = 0;
	float z = 0;
	float r = 0;
	
	for ( int i = 0 ; i < this->getNbFrameC() ; i++ )
	{
		z = this->getFrame(0,0,i,0)->getMiddlePoint()[2];
		k = ( z - _vertex[2] ) / _vector[2];
		
		x = _vertex[0] + ( k * _vector[0] );
		y = _vertex[1] + ( k * _vector[1] );
		
		r = distPoint( _vertex, x, y, z );
		
		if ( r < _rMax )
		{
			/* Et on incrémente cette case dans l'espace de Hough */
			this->addCircle( Circle(x,y,z,r) );
		}
	}
}


void HoughSpace4D::increment( int _a, int _b, int _c, int _r, Circle _circle)
{
        this->frames[_a][_b][_c][_r].increment(_circle);
        this->scoreTotal ++;
}

vector<Circle> HoughSpace4D::getMaximums()
{
	bool test = false;
	vector<Circle> rslt;

	for ( int i = 0 ; i < nbFrameA ; i++ )
		for ( int j = 0 ; j < nbFrameB ; j++ )
			for ( int k = 0 ; k < nbFrameC ; k++ )
				for ( int l = 0 ; l < nbFrameR ; l++ )
				{
					int score1 = this->getScore(i,j,k,l);
					
					if ( score1 != 0 )
					{
						test = false;
						
						for ( int m = -1 ; m <= 1 && test == false ; m++ )
							for ( int n = -1 ; n <= 1 && test == false ; n++ )
								for ( int o = -1 ; o <= 1 && test == false ; o++ )
									for ( int p = -1 ; p <= 1 && test == false ; p++ )
									{
										if ( !(m == 0 && n == 0 && o == 0 && p == 0) )
										{
											int m2 = i+m, n2 = j+n, o2 = k+o, p2 = l+p;
											mirror( m2, n2, o2, p2, nbFrameA, nbFrameB, nbFrameC, nbFrameR );
											
											int score2 = this->getScore(m2,n2,o2,p2);
											
											if( score2 > score1 )
												test = true;
										}
									}
	
						if(test == false)
						{
							rslt.push_back ( Circle (  ((float)i * frameSizeA) + this->bot[0] + (frameSizeA/(float)2),
										   ((float)j * frameSizeB) + this->bot[1] + (frameSizeB/(float)2),
										   ((float)k * frameSizeC) + this->bot[2] + (frameSizeC/(float)2),
										   ((float)l * frameSizeR) + this->bot[3] + (frameSizeR/(float)2)
										   ));
						}
					}
				}
	
        return rslt;
}

vector<Circle> HoughSpace4D::getMaximumsWithThres(int _thresh, int _neighborhood)
{
	bool test = false;
	vector<Circle> rslt;
	
	if ( _neighborhood <= 0 )
	{
		cout<<"Bad neighborhood parameter at \"HoughSpace4D::getMaximumsWithThres(int _thresh, int _neighborhood)\""<<endl;
		return rslt;
	}

	for ( int i = 0 ; i < nbFrameA ; i++ )
		for ( int j = 0 ; j < nbFrameB ; j++ )
			for ( int k = 0 ; k < nbFrameC ; k++ )
				for ( int l = 0 ; l < nbFrameR ; l++ )
				{
					int score1 = this->getScore(i,j,k,l);
					
					if ( score1 > _thresh )
					{
						test = false;
						
						for ( int m = -_neighborhood ; m <= _neighborhood && test == false ; m++ )
							for ( int n = -_neighborhood ; n <= _neighborhood && test == false ; n++ )
								for ( int o = -_neighborhood ; o <= _neighborhood && test == false ; o++ )
									for ( int p = -_neighborhood ; p <= _neighborhood && test == false ; p++ )
									{
										if ( !(m == 0 && n == 0 && o == 0 && p == 0) )
										{
											int m2 = i+m, n2 = j+n, o2 = k+o, p2 = l+p;
											mirror( m2, n2, o2, p2, nbFrameA, nbFrameB, nbFrameC, nbFrameR );
											
											int score2 = this->getScore(m2,n2,o2,p2);
											
											if( score2 > score1 )
												test = true;
										}
									}
	
						if(test == false)
						{
                                                        rslt.push_back ( Circle (  ((float)i * frameSizeA) + this->bot[0] + (frameSizeA/(float)2),
										   ((float)j * frameSizeB) + this->bot[1] + (frameSizeB/(float)2),
										   ((float)k * frameSizeC) + this->bot[2] + (frameSizeC/(float)2),
                                                                                   ((float)l * frameSizeR) + this->bot[3] + (frameSizeR/(float)2),
                                                                                   score1
										   ));
						}
					}
				}
	
        return rslt;
}
